﻿#region

using System;
using System.Collections.Generic;

#endregion

namespace HouseHoldBudget.Core.Infrastructure
{
    /// <summary>
    ///   A statically compiled "singleton" used to store objects throughout the lifetime of the app domain. Not so much singleton in the pattern's sense of the word as a standardized way to store single instances.
    /// </summary>
    /// <typeparam name="T"> The type of object to store. </typeparam>
    /// <remarks>
    ///   Access to the instance is not synchrnoized.
    /// </remarks>
    public class Singleton<T> : Singleton
    {
        #region Readonly & Static Fields

        private static T instance;

        #endregion

        #region Class Properties

        /// <summary>
        ///   The singleton instance for the specified type T. Only one instance (at the time) of this object for each type of T.
        /// </summary>
        public static T Instance
        {
            get
            {
                return instance;
            }
            set
            {
                instance = value;
                AllSingletons[typeof (T)] = value;
            }
        }

        #endregion
    }

    /// <summary>
    ///   Provides a singleton list for a certain type.
    /// </summary>
    /// <typeparam name="T"> The type of list to store. </typeparam>
    public class SingletonList<T> : Singleton<IList<T>>
    {
        #region Constructors

        static SingletonList()
        {
            Singleton<IList<T>>.Instance = new List<T>();
        }

        #endregion

        #region Class Properties

        /// <summary>
        ///   The singleton instance for the specified type T. Only one instance (at the time) of this list for each type of T.
        /// </summary>
        public new static IList<T> Instance
        {
            get
            {
                return Singleton<IList<T>>.Instance;
            }
        }

        #endregion
    }

    /// <summary>
    ///   Provides a singleton dictionary for a certain key and vlaue type.
    /// </summary>
    /// <typeparam name="TKey"> The type of key. </typeparam>
    /// <typeparam name="TValue"> The type of value. </typeparam>
    public class SingletonDictionary<TKey, TValue> : Singleton<IDictionary<TKey, TValue>>
    {
        #region Constructors

        static SingletonDictionary()
        {
            Singleton<Dictionary<TKey, TValue>>.Instance = new Dictionary<TKey, TValue>();
        }

        #endregion

        #region Class Properties

        /// <summary>
        ///   The singleton instance for the specified type T. Only one instance (at the time) of this dictionary for each type of T.
        /// </summary>
        public new static IDictionary<TKey, TValue> Instance
        {
            get
            {
                return Singleton<Dictionary<TKey, TValue>>.Instance;
            }
        }

        #endregion
    }

    /// <summary>
    ///   Provides access to all "singletons" stored by <see cref="Singleton{T}" /> .
    /// </summary>
    public class Singleton
    {
        #region Readonly & Static Fields

        private static readonly IDictionary<Type, object> allSingletons;

        #endregion

        #region Constructors

        static Singleton()
        {
            allSingletons = new Dictionary<Type, object>();
        }

        #endregion

        #region Class Properties

        /// <summary>
        ///   Dictionary of type to singleton instances.
        /// </summary>
        public static IDictionary<Type, object> AllSingletons
        {
            get
            {
                return allSingletons;
            }
        }

        #endregion
    }
}